home *** CD-ROM | disk | FTP | other *** search
/ Aminet 50 / Aminet 50 (2002)(GTI - Schatztruhe)[!][Aug 2002].iso / Aminet / text / edit / tecoc-146.lha / pushex.c < prev    next >
C/C++ Source or Header  |  1991-07-05  |  5KB  |  180 lines

  1. /*****************************************************************************
  2.  
  3.     PushEx ()
  4.     Reduce ()
  5.     Push an item on the stack and try to reduce it.
  6.  
  7. *****************************************************************************/
  8.  
  9. #include "zport.h"        /* define portability identifiers */
  10. #include "tecoc.h"        /* define general identifiers */
  11. #include "defext.h"        /* define external global variables */
  12. #include "dchars.h"        /* define identifiers for characters */
  13. #include "deferr.h"        /* define identifiers for error messages */
  14.  
  15. /*****************************************************************************
  16.  
  17.     Reduce()
  18.  
  19.     This function attempts to reduce the expression stack.  It is called
  20. by PushEx when the stack has two or more values on it and therefore might be
  21. reduceable.
  22.  
  23. *****************************************************************************/
  24.  
  25. #if USE_PROTOTYPES
  26. static DEFAULT Reduce(void);
  27. #endif
  28.  
  29. static DEFAULT Reduce()        /* reduce the expression stack */
  30. {
  31.     ESptr    ESp1;        /* 1st thing on stack (top) */
  32.     ESptr    ESp2;        /* 2nd thing on stack (top-1) */
  33.     ESptr    ESp3;        /* 3rd thing on stack (top-2) */
  34.     WORD    OnStack;    /* number of items on stack */
  35.     LONG    x;        /* temporary operand */
  36.     LONG    y;        /* temporary operand */
  37.  
  38.     FOREVER {        /* reduce until you can't reduce anymore */
  39.         OnStack = EStTop - EStBot;
  40.         if (OnStack < 0) {    /* nothing on stack */
  41.             break;
  42.         }
  43.         ESp1 = &(EStack[EStTop]);
  44.         ESp2 = ESp1 - 1;
  45.         ESp3 = ESp2 - 1;
  46.         if (OnStack >= 3) {
  47. /*
  48.  * if it's x+y, x-y, x*y, x/y, x&y or x#y, reduce it
  49.  */
  50.             if (ESp1->ElType == OPERAND  &&
  51.                 ESp2->ElType == OPERATOR &&
  52.                 ESp3->ElType == OPERAND  &&
  53.                 ESp2->Elemnt != ')' &&
  54.                 ESp2->Elemnt != '(') {
  55.                 x = ESp3->Elemnt;
  56.                 y = ESp1->Elemnt;
  57.                 switch ((char)ESp2->Elemnt) {
  58.                 case '+':    x += y;        break;
  59.                 case '-':    x -= y;        break;
  60.                 case '*':    x *= y;        break;
  61.                 case '/':    x /= y;        break;
  62.                 case '&':    x &= y;        break;
  63.                 case '#':    x |= y;        break;
  64.                 }
  65.                 ESp3->Elemnt = x;
  66. /*
  67.  * ESp3->ElType is already OPERAND
  68.  */
  69.                 EStTop -= 2;
  70.                 continue;
  71.             } else {
  72. /*
  73.  * if it's (x),  reduce it to x
  74.  */
  75.                 if (ESp1->ElType == OPERATOR &&
  76.                     ESp2->ElType == OPERAND  &&
  77.                     ESp3->ElType == OPERATOR &&
  78.                     ESp1->Elemnt == ')' &&
  79.                     ESp3->Elemnt == '(') {
  80.                     ESp3->Elemnt = ESp2->Elemnt;
  81.                     ESp3->ElType = OPERAND;
  82.                     EStTop -= 2;
  83.                     continue;
  84.                 }
  85.             }
  86.         }
  87.         if (OnStack >= 2) {
  88. /*
  89.  * if it's +x or -x, reduce it to + or - x
  90.  */
  91.             if (ESp1->ElType == OPERAND  &&
  92.                 ESp2->ElType == OPERATOR &&
  93.                 (ESp2->Elemnt == '+' || ESp2->Elemnt == '-')) {
  94.                 x = ESp1->Elemnt;
  95.                 if (ESp2->Elemnt == '-') {
  96.                     x = -x;
  97.                 }
  98.                 ESp2->Elemnt = x;
  99.                 ESp2->ElType = OPERAND;
  100.                 --EStTop;
  101.                 continue;
  102.             }
  103.         }
  104.         if (OnStack >= 1) {
  105. /*
  106.  * check for one's complement operator ^_.  This operator complements the
  107.  * PRECEDING argument.
  108.  */
  109.             if (ESp1->ElType == OPERATOR &&
  110.                 ESp1->Elemnt == USCHAR) {
  111.                 if (OnStack == 1 || ESp2->ElType != OPERAND) {
  112.                     ErrMsg(ERR_NAB); /* no arg before ^_ */
  113.                     return FAILURE;
  114.                 }
  115.                 ESp2->Elemnt = ~(ESp2->Elemnt);
  116. /*
  117.  * ESp2->ElType is already OPERAND
  118.  */
  119.                 --EStTop;
  120.                 continue;
  121.             }
  122.         }
  123.         break;        /* can't reduce anymore */
  124.     }
  125.     return (SUCCESS);
  126. }
  127.  
  128. /*****************************************************************************
  129.  
  130.     PushEx()
  131.  
  132.     This function pushes an item onto the expression stack.  The
  133. expression stack implement's TECO's expression handling capability.  For
  134. instance,  if a command like 10+qa=$ is executed,  then three values are
  135. pushed onto the expression stack: 10, plus sign and the value of qa.  Each
  136. time a value is pushed onto the expression stack,  the Reduce function is
  137. called to see if the stack can be reduced.  In the above example,  Reduce
  138. would cause the stack to be reduced when the value of qa is pushed,  because
  139. the expression can be evaluated at that time.
  140.  
  141. *****************************************************************************/
  142.  
  143. DEFAULT PushEx(Item, EType)    /* push onto expression stack */
  144. LONG Item;
  145. DEFAULT EType;
  146. {
  147. #if DEBUGGING
  148.     static char *DbgFNm = "PushEx";
  149.     if (EType == OPERAND) {
  150.         sprintf(DbgSBf,"Item = %ld, EType = OPERAND", (LONG)Item);
  151.     } else if (EType == OPERATOR) {
  152.         sprintf(DbgSBf,"Item = '%c', EType = OPERATOR", (char)Item);
  153.     } else {
  154.         DbgFEn(3,DbgFNm,"FAILURE, illegal item type");
  155.         TAbort(EXIT_FAILURE);
  156.     }
  157.     DbgFEn(3,DbgFNm,DbgSBf);
  158. #endif
  159.  
  160.     if (++EStTop >= EXS_SIZE) {        /* if expression stack full */
  161.         ErrMsg(ERR_PDO);        /* push-down list overflow */
  162.         DBGFEX(3,DbgFNm,"FAILURE, expression stack full");
  163.         return FAILURE;
  164.     }
  165.  
  166.     EStack[EStTop].Elemnt = Item;        /* put item on stack */
  167.     EStack[EStTop].ElType = EType;        /* put item type on stack */
  168.     if (EStTop > (EStBot + 1)) {        /* if stack might reduce */
  169.         if (Reduce() == FAILURE) {    /* reduce expression stack */
  170.             DBGFEX(3,DbgFNm,"FAILURE, Reduce() failed");
  171.             return FAILURE;
  172.         }
  173.     }
  174. #if DEBUGGING
  175.     sprintf(DbgSBf,"EStTop = %ld, EStBot = %ld", (LONG)EStTop, (LONG)EStBot);
  176.     DbgFEx(3,DbgFNm,DbgSBf);
  177. #endif
  178.     return SUCCESS;
  179. }
  180.